package com.gobang.common.task;

import com.gobang.service.ConnectionManagerService;
import com.gobang.service.MessageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * 心跳检测定时任务
 * 负责定期发送心跳消息和清理超时连接，服务器要防止僵尸连接占用服务器资源，确保连接活性
 * 
 * @author System
 * @since 1.0.0
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class HeartbeatTask {
    
    private final MessageService messageService;
    private final ConnectionManagerService connectionManagerService;
    
    // 心跳发送间隔：30秒
    private static final long HEARTBEAT_INTERVAL = 30 * 1000;
    
    // 连接超时时间：60秒
    private static final long CONNECTION_TIMEOUT = 300 * 1000;
    
    /**
     * 定期发送心跳消息
     * 每30秒执行一次，向所有在线用户发送心跳消息
     */
    @Scheduled(fixedRate = HEARTBEAT_INTERVAL)
    public void sendHeartbeat() {
        try {
            Set<Long> onlineUsers = connectionManagerService.getAllOnlineUsers();
            if (onlineUsers.isEmpty()) {
                log.debug("当前无在线用户，跳过心跳发送");
                return;
            }
            
            log.debug("开始发送心跳消息，在线用户数：{}", onlineUsers.size());
            
            for (Long userId : onlineUsers) {
                try {
                    messageService.sendHeartbeat(userId);
                } catch (Exception e) {
                    log.warn("发送心跳消息失败：userId={}", userId, e);
                }
            }
            
            log.debug("心跳消息发送完成，发送数量：{}", onlineUsers.size());
        } catch (Exception e) {
            log.error("心跳发送任务异常", e);
        }
    }
    
    /**
     * 定期清理超时连接
     * 每60秒执行一次，清理超过60秒未响应心跳的连接
     */
    @Scheduled(fixedRate = CONNECTION_TIMEOUT)
    public void cleanTimeoutConnections() {
        try {
            int cleanedCount = connectionManagerService.cleanTimeoutConnections(CONNECTION_TIMEOUT);
            if (cleanedCount > 0) {
                log.info("清理超时连接完成，清理数量：{}", cleanedCount);
            } else {
                log.debug("无超时连接需要清理");
            }
        } catch (Exception e) {
            log.error("清理超时连接任务异常", e);
        }
    }
    
    /**
     * 连接统计日志
     * 每5分钟执行一次，输出连接统计信息
     */
    @Scheduled(fixedRate = 5 * 60 * 1000)
    public void logConnectionStats() {
        try {
            Set<Long> onlineUsers = connectionManagerService.getAllOnlineUsers();
            log.info("WebSocket连接统计 - 在线用户数：{}", onlineUsers.size());
        } catch (Exception e) {
            log.error("连接统计任务异常", e);
        }
    }
} 